import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
//基于NIO非阻塞的简易聊天室 --- 服务器端
public class SelectorDemo_server {
    public static void main(String[] args) throws IOException {
        System.out.println("----server start----");
        //1.获取通道(这个通道专门负责监听客户端发来的连接请求)
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        //2.切换为非阻塞模式
        serverSocketChannel.configureBlocking(false);
        //3.绑定连接的端口
        serverSocketChannel.bind(new InetSocketAddress(9999));
        //4.获取选择器Selector
        Selector selector = Selector.open();
        //5.将客户端的通道(用于监听客户端请求的通道)注册到选择器上,并指定监听接收事件
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        //6.使用Selector选择器轮询已经就绪好的事件
        while(selector.select() > 0 ){
            //7.获取选择器中的所有注册的通道中已经就绪好的事件
            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
            //8.开始遍历这些准备好的事件
            while(iterator.hasNext()){
                //提取这个事件
                SelectionKey key = iterator.next();
                //9.判断这个事件具体是什么
                if(key.isAcceptable()){
                    //10.直接获取当前接入的客户端通道
                    SocketChannel accept = serverSocketChannel.accept();
                    //11.切换成非阻塞模式
                    accept.configureBlocking(false);
                    //12.将当前客户端通道注册到选择器
                    accept.register(selector,SelectionKey.OP_READ);
                }
                else if(key.isReadable()){
                    //13.获取当前选择器上的读就绪事件
                    SocketChannel socketChannel = (SocketChannel) key.channel(); //通过 channel()方法反向获取客户端通道
                    //14.读取数据
                    ByteBuffer buffer = ByteBuffer.allocate(1024);
                    int len;
                    while((len = socketChannel.read(buffer)) > 0){        //这里 > 0 很关键！！！  如果写 ！= -1 , 会有奇怪的bug
                        buffer.flip();
                        System.out.println(new String(buffer.array(),0,len));  //buffer.array()方法能更有效地将数组支持的缓冲区传递给本机
                        buffer.clear();   //清空buffer
                    }
                }
            }
            iterator.remove(); //处理完毕之后需要移除当前事件

        }

    }
}